﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;
using System.Collections;
using ICSharpCode.SharpZipLib.Zip;
using nwrole.lib;

namespace nwrole.service
{
    internal static class StorageUtil
    {
        #region Plugins
        public static IDictionary PluginToDictionary (Plugin plugin)
        {
            return new Dictionary<string, object>
            {
                { "id", plugin.Id.ToString("N") },
                { "name", plugin.Name },
                { "description", plugin.Description },
                { "author", plugin.Author },
                { "assembly", plugin.Assembly },
                { "class-name", plugin.ClassName },
                { "created", plugin.Created },
                { "updated", plugin.Updated },
                { "configuration", plugin.Configuration },
                { "added", plugin.Added }
            };
        }

        public static Plugin PluginFromDictionary (IDictionary dict)
        {
            return new Plugin
            {
                Id = new Guid(dict["id"] as string),
                Name = dict["name"] as string,
                Description = dict["description"] as string,
                Author = dict["author"] as string,
                Assembly = dict["assembly"] as string,
                ClassName = dict["class-name"] as string,
                Created = (DateTime)dict["created"],
                Updated = (DateTime)dict["updated"],
                Configuration = (Dictionary<string, object>)dict["configuration"],
                Added = (DateTime)dict["added"]
            };
        }

        public static void StorePlugin (PluginBundle bundle)
        {
            string pluginDirectory = Path.Combine(Configuration.PluginsDirectory, bundle.Id.ToString("N"));
            if (Directory.Exists(pluginDirectory))
                Directory.Delete(pluginDirectory, true);
            Directory.CreateDirectory(pluginDirectory);

            foreach (string file in bundle.Files)
                File.Copy(file, Path.Combine(pluginDirectory, Path.GetFileName(file)));
        }

        public static void DeletePlugin (Guid id)
        {
            string pluginDirectory = Path.Combine(Configuration.PluginsDirectory, id.ToString("N"));
            if (Directory.Exists(pluginDirectory))
                Directory.Delete(pluginDirectory, true);
        }
        #endregion

        #region Solutions
        public static IDictionary SolutionToDictionary (Solution solution)
        {
            var dict = new Dictionary<string, object>
            {
                { "id", solution.Id.ToString("N") },
                { "name", solution.Name },
                { "description", solution.Description },
                { "author", solution.Author },
                { "created", solution.Created },
                { "updated", solution.Updated },
                { "added", solution.Added },
                { "deployed", solution.Deployed },
                { "state", solution.State },
                { "services", new List<object>() }
            };
            foreach (Solution.Service service in Configuration.ServicesInSolution(solution.Id))
                ((List<object>)dict["services"]).Add(ServiceToDictionary(service));
            return dict;
        }

        public static Solution SolutionFromDictionary (IDictionary dict)
        {
            Solution solution = new Solution
            {
                Id = new Guid(dict["id"] as string),
                Name = dict["name"] as string,
                Description = dict["description"] as string,
                Author = dict["author"] as string,
                Created = (DateTime)dict["created"],
                Updated = (DateTime)dict["updated"],
                Added = (DateTime)dict["added"],
                Deployed = (dict["deployed"] == null) ? (DateTime?)null : (DateTime?)Convert.ToDateTime(dict["deployed"]),
                State = (Solution.SolutionState)Enum.Parse(typeof(Solution.SolutionState), dict["state"] as string)
            };
            foreach (object obj in (IEnumerable)dict["services"])
                Configuration.Services.Add(StorageUtil.ServiceFromDictionary((IDictionary)obj, solution.Id));
            return solution;
        }

        public static void StoreSolution (SolutionBundle bundle)
        {
            string solutionDirectory = Path.Combine(Configuration.SolutionsDirectory, bundle.Id.ToString("N"));
            if (Directory.Exists(solutionDirectory))
                Directory.Delete(solutionDirectory, true);
            Directory.CreateDirectory(solutionDirectory);
            foreach (string file in bundle.Files)
                File.Copy(file, Path.Combine(solutionDirectory, Path.GetFileName(file)));
        }

        public static void DeleteSolution (Guid id)
        {
            string solutionDirectory = Path.Combine(Configuration.SolutionsDirectory, id.ToString("N"));
            if (Directory.Exists(solutionDirectory))
                Directory.Delete(solutionDirectory, true);
        }
        #endregion

        #region Services
        public static IDictionary ServiceToDictionary (Solution.Service service)
        {
            var dict = new Dictionary<string, object>
            {
                { "id", service.Id.ToString("N") },
                { "name", service.Name },
                { "description", service.Description },
                { "username", service.Username },
                { "password", service.Password },
                { "instances", new List<object>() }
            };
            foreach (Solution.Instance instance in Configuration.InstancesInService(service.Id))
                ((List<object>)dict["instances"]).Add(InstanceToDictionary(instance));
            return dict;
        }

        public static Solution.Service ServiceFromDictionary (IDictionary dict, Guid solutionId)
        {
            Solution.Service service = new Solution.Service
            {
                Id = new Guid(dict["id"] as string),
                Name = dict["name"] as string,
                Description = dict["description"] as string,
                Username = dict["username"] as string,
                Password = dict["password"] as string,
                SolutionId = solutionId
            };
            foreach (object obj in (IEnumerable)dict["instances"])
                Configuration.Instances.Add(InstanceFromDictionary((IDictionary)obj, service.Id, solutionId));
            return service;
        }
        #endregion

        #region Instances
        public static IDictionary InstanceToDictionary (Solution.Instance instance)
        {
            return new Dictionary<string, object>
            {
                { "id", instance.Id.ToString("N") },
                { "plugin-id", instance.PluginId.ToString("N") },
                { "configuration", instance.Configuration }
            };
        }

        public static Solution.Instance InstanceFromDictionary (IDictionary dict, Guid serviceId, Guid solutionId)
        {
            return new Solution.Instance
            {
                Id = new Guid(dict["id"] as string),
                PluginId = new Guid(dict["plugin-id"] as string),
                Configuration = (Dictionary<string, object>)dict["configuration"],
                ServiceId = serviceId,
                SolutionId = solutionId
            };
        }
        #endregion
    }
}
